package lib;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Provides various methods for doing File IO
 *
 * @author abhip
 *
 */
public class FileIO 
{
    /**
     * Appends given data to the file If file does not exist, creates one and
     * writes data to it
     *
     * @param file
     * @param data
     * @throws IOException
     */
    public static void AppendLineToFile(File file, String data)
            throws IOException
    {
        ArgumentValidator.IsNotNull("file", file);
        // data can be empty string which means append new line
        // hence, only do null check
        ArgumentValidator.IsNotNull("data", data);

        if (!file.exists())
        {
            CreateFile(file);
        }

        BufferedWriter bufWriter = new BufferedWriter(
                new FileWriter(file, true));
        bufWriter.write(data);
        bufWriter.newLine();
        bufWriter.close();
    }

    /**
     * Creates file on disk
     *
     * @param file
     *            Name of the file to be created
     * @return true if file created successfully
     * @throws IOException
     */
    public static void CreateFile(File file) throws IOException
    {
        ArgumentValidator.IsNotNull("file", file);

        if (file.exists()) {
            throw new IOException(String.format(
                    "Cannot create new file '%s', file already exists!", file));
        }

        File parentDir = file.getParentFile();
        parentDir.mkdirs();

        // Devnote (abhip):
        // createNewFile() returns false only when the file already exists.
        // Since that is already handled previously as an IOException,
        // we can ignore the return value which is bound to be true
        file.createNewFile();
    }

    /**
     * Gets a particular line from the given file
     *
     * @param file
     * @param lineNumber
     * @return
     * @throws IOException
     */
    public static String GetLineFromFile(File file, int lineNumber) throws IOException
    {
        ArgumentValidator.IsNotNull("file", file);
        ArgumentValidator.IsGreaterThan("lineNumber", lineNumber, 0);

        int curLineNumber = 0;
        String curLine = null;

        BufferedReader br = new BufferedReader(new FileReader(file));
        while ((curLine = br.readLine()) != null) {
            if (++curLineNumber == lineNumber) {
                return curLine;
            }
        }

        throw new IOException(String.format(
                "File: %s has only %d lines. Cannot fetch line %d",
                file.getAbsolutePath(), curLineNumber, lineNumber));
    }

    /**
     * Overwrites contents of file with given data. If file does not exist, creates one.
     * @param file
     * @param data
     * @throws IOException
     */
    public static void OverwriteFile(File file, String data)
            throws IOException
    {
        ArgumentValidator.IsNotNull("file", file);
        // data can be empty string which means append new line
        // hence, only do null check
        ArgumentValidator.IsNotNull("data", data);

        if (!file.exists())
        {
            CreateFile(file);
        }

        BufferedWriter bufWriter = new BufferedWriter(
                new FileWriter(file, false));
        bufWriter.write(data);
        bufWriter.newLine();
        bufWriter.close();
    }
}
